import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
class SingleClassContext 
{
 
	    static int method_count, accesses_count;	
	 	String [ ]fields;
	    String field;
	    String methodStmnts, accessStmnts;
	    String[]methodNames;
	    String [ ][ ]association;
	    int fieldsCount;	
		int methodCount;
		int accessCount;
	    String [ ]accesses;
		
		public static int countFields() throws IOException{
		int count=0;
	    FileInputStream fstreamForMemberFields;
		try 
		{
			fstreamForMemberFields = new FileInputStream("InfoFiles/Members.txt");
			DataInputStream inForMemberFields = new DataInputStream(fstreamForMemberFields);
			BufferedReader brMemberFields = new BufferedReader(new InputStreamReader(inForMemberFields));
			 while ((brMemberFields.readLine()) != null)   {
			      count++;
			 }
			inForMemberFields.close();
		} catch (FileNotFoundException e) {		
			
			e.printStackTrace();
		}   
		finally{
			
			
		}
	    
	  
	  return count;
  }		
  public static int countMethods() throws IOException
  {
	  int count=0;
	  FileInputStream fstreamForMethodStatement = new FileInputStream("InfoFiles/Methods.txt");   
	  DataInputStream inForMethodStmnt = new DataInputStream(fstreamForMethodStatement);
	  BufferedReader brMethodStmnt = new BufferedReader(new InputStreamReader(inForMethodStmnt));
	  
	    String methodStmnts = brMethodStmnt.readLine();
	    
	    while (  methodStmnts!=null )   {
	    		count++;    		    
	    	    methodStmnts = brMethodStmnt.readLine();
	    }	        	  
	  
	  inForMethodStmnt.close();	  
	  method_count=count;
	  return count;
  }
  public static int countAccess() throws IOException
  {
	  //Count all entries in Access.txt file including "Start of Method" and "End of Method" deliemeter
	  int count=0;
	  FileInputStream fstreamForAccessesStatement = new FileInputStream("InfoFiles/Accesses.txt");   
	  DataInputStream inForAccessesStmnt = new DataInputStream(fstreamForAccessesStatement);
	  BufferedReader brAccessesStmnt = new BufferedReader(new InputStreamReader(inForAccessesStmnt));
	  
	    String accessesStmnts = brAccessesStmnt.readLine();
	    
	    while (  accessesStmnts!=null )   {
	    		count++;    		    
	    	    accessesStmnts = brAccessesStmnt.readLine();
	    }	        	  
	  
	  inForAccessesStmnt.close();	  
	  accesses_count=count;
	  return count;
  }
  boolean isMethodName(int index)
  {
	  if(index>0)
		  return accesses[index-1].contains("Start of Method");
	  return false;
  }  
  public void extractInfo(String inputFileName, String outputFileName){
	  try{
		 	
		 	SingleClassParser newParser=new SingleClassParser();
		 	newParser.parseSingleClass(inputFileName);
		 		
		   		
			fieldsCount=countFields();	
			methodCount=countMethods();
			accessCount=countAccess();
			
		    FileInputStream fstreamForMemberFields = new FileInputStream("InfoFiles/Members.txt");   
		    DataInputStream inForMemberFields = new DataInputStream(fstreamForMemberFields);
		    BufferedReader brMemberFields = new BufferedReader(new InputStreamReader(inForMemberFields));
		    
		    FileInputStream fstreamForMethodStatement = new FileInputStream("InfoFiles/Methods.txt");   
		    DataInputStream inForMethodStmnt = new DataInputStream(fstreamForMethodStatement);
		    BufferedReader brMethodStmnt = new BufferedReader(new InputStreamReader(inForMethodStmnt));
		    
		    FileInputStream fstreamForAccessStatement = new FileInputStream("InfoFiles/Accesses.txt");   
		    DataInputStream inForAccessStmnt = new DataInputStream(fstreamForAccessStatement);
		    BufferedReader brAccessStmnt = new BufferedReader(new InputStreamReader(inForAccessStmnt));
		    
		    fields=new String[fieldsCount];
		    methodNames= new String[method_count];
		    accesses= new String[accessCount];
		    methodStmnts=null;
		    association=new String[methodCount][fieldsCount];
		    int i=0, j=0, k=0;
		    while ((field=brMemberFields.readLine()) != null)   {		    	
			  	fields[i++]=field;
			}		   
		    while ((methodStmnts=brMethodStmnt.readLine()) != null)   {    	
			  	methodNames[j++]=methodStmnts;
			}    
		    while ((accessStmnts=brAccessStmnt.readLine()) != null)   {    	
			  	accesses[k++]=accessStmnts;			  	
			}    
		    for(int iterMethod=0; iterMethod<methodCount; iterMethod++)
		    {
		    	for(int iterField=0; iterField<fieldsCount; iterField++)
		    	{
		    		association[iterMethod][iterField]="0";
		    		
		    	}
		    	    		
		    }	   		    
		    
		    for(int x=0; x<methodCount; x++){	    	
		    	
    	      	for(int z=0; z<accessCount; z++){
    	      		
    	      	
    	      		
    	      		if(accesses[z].contentEquals(methodNames[x]) && isMethodName(z)){    	      		    
    	      			
    	      			accesses[z]="-1"; // Method is Visited    	      			
    	      					
	    	      		while(!accesses[z].contentEquals("End of Method")&& z<accessCount)
	    	      		{
	    	      			
	    	      	
	    	      			
	    	      			if(accesses[z].contentEquals("Start of Method")){
	    	      					while(!accesses[z].contentEquals("End of Method") && z< accessCount){	    	      						
	    	      						  z++;	    	      		
	    	      					}	    	      					
	    	      			}    	      		
	    	      			else
	    	      			{
	    	      				
	    	      				for(int iterFields=0; iterFields<fieldsCount; iterFields++)
	    	      				{	    	      					
	    	      					if(accesses[z].contentEquals(fields[iterFields])){
	    	      						
	    	      						association[x][iterFields]="1";	    	      				
	    	      					
	    	      					}	
	    	      				}
	    	      				z++;
	    	      			}
	    	      		}
    	      		    z=accessCount; // break the loop;
    	      		}
    	      	}
		    			    		    		
			}		   
		  
		    	inForMemberFields.close();
			    inForMethodStmnt.close();
			
			}  catch (Exception e){
		    	
				e.printStackTrace();
		    }
 
  
  
  }

  

  public void generateConexpInput(String inputFileName, String outputFileName)  {
	try{
	  extractInfo(inputFileName, outputFileName);	

	    BufferedWriter output;		
	    output = new BufferedWriter(new FileWriter(outputFileName));
	    output.write(";");
	    for(int iter=0; iter<fieldsCount; iter++)
	    {    
	    	output.write(fields[iter]);    
	    	output.write(";");
	    }
	    
	    output.newLine();
	    output.newLine();
	    for(int x=0; x<methodCount; x++)
	    {	    	
	    	output.write(methodNames[x]);
            output.write(";");
	    	for(int y=0; y<fieldsCount; y++)
	    	{    		
	    		output.write(association[x][y]);    		
	    		output.write(";");
	    	}    	
	    	output.newLine();
	    }	
	   
	   
		output.close();

  }catch (Exception e){
  	
	  e.printStackTrace();
   }
		
  

}
 
 
  public void generateGaliciaInput(String inputFileName, String outputFileName){
	try{
	   
	  		extractInfo(inputFileName, outputFileName);	
	  		BufferedWriter output;		
	 	    output = new BufferedWriter(new FileWriter(outputFileName));
	        output.write("[Relational Context]\rSingleClass\r[Binary Relation]\rSingleClass\r");
		   
	    
	    
	    //writing methods
	    
	    for(int x=0; x<methodCount; x++)
	    {
	    	output.write(methodNames[x]);
	    	 output.write(" | ");
	    }
	   
	
	    output.write("\r");
	    
	    //writing Fields
	    for(int iter=0; iter<fieldsCount; iter++)
	    {    
	    	output.write(fields[iter]);    
	    	output.write(" | ");
	    }
	    
	    
	    //writing associations
	    output.write("\r");
	    for(int x=0; x<methodCount; x++)
	    {
	   
	    	for(int y=0; y<fieldsCount; y++)
	    	{    		
	    		output.write(association[x][y]);    		
	    		output.write(" ");
	    	}    	
	    
	   
	    	output.write("\r");
	    }	
	    
	       output.write("[END Relational Context]");		
		   output.write("\r");		   
		   output.close();
	    }catch (Exception e){
	    	
	    	e.printStackTrace();
		}
	    
		
}
 

}






